package com.lovo.web.service.impl;

import com.lovo.web.bean.DisplayBean;
import com.lovo.web.bean.ProductInfoBean;
import com.lovo.web.mapper.IDisplayMapper;
import com.lovo.web.mapper.IProductInfoMapper;
import com.lovo.web.service.IDisplayService;
import org.redisson.api.RLock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
@Transactional
public class DisplayServiceImpl implements IDisplayService {

    @Autowired
    private IDisplayMapper mapper;
    @Autowired
    RedisTemplate redisTemplate;
    @Autowired
    RLock rLock;
    @Autowired
    IProductInfoMapper infoMapper;


    @Override
    public void add(DisplayBean bean) {
        mapper.insert(bean);
    }

    @Override
    public void delete() {
        mapper.delete();
    }

    //每天早上九点从后台数据库拉取前一天销售量最高的八件商品
    @Scheduled(cron = "0 1-59 * * * ? ")
    @Override
    public void genxing() {
        this.delete();
        redisTemplate.delete("display");
        List<ProductInfoBean> productList = infoMapper.findHotProductLst();
        for (ProductInfoBean p:productList){
            DisplayBean displayBean = new DisplayBean();
            displayBean.setImg(p.getImg());
            displayBean.setPrice(p.getPrice());
            displayBean.setProductName(p.getProductName());
            displayBean.setType(p.getSpecs());
            this.add(displayBean);
        }
    }

    @Override
    public Object getDisplayCache() {
        String key = "display";
        Object obj = null;
        if (redisTemplate.hasKey(key)) {
            obj = redisTemplate.opsForValue().get(key);
        } else {//2.没有缓存
            try {
                //3.使用竞争锁解决缓存穿透
                boolean lock = rLock.tryLock(0, 10, TimeUnit.SECONDS);
                if (lock) {//4抢到锁，进去执行，10秒内没有执行，强行回收锁，防止死锁
                    obj = mapper.selectList(null);
                    redisTemplate.opsForValue().set(key, obj, 1, TimeUnit.DAYS);
                    rLock.unlock();
                } else {//6没抢到锁,进入睡眠等待，苏醒后继续进入本方法查看是否已有缓存
                    //7有则自己返回缓存，没有则继续竞争锁,从第三步开始执行
                    Thread.sleep(500);
                    this.getDisplayCache();
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        return obj;
    }
}
